package com.ssf.framework.shiro.session.mgt;

import com.raiyee.hi.boss.redis.RedisUtil;
import com.raiyee.hi.boss.shiro.session.iface.ShiroSessionRepositoryAware;
import com.raiyee.hi.boss.util.SerializeUtil;
import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.ShardedJedis;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by liolay on 15-7-27.
 */
public class ShiroSessionDaoRedisAdapter implements ShiroSessionRepositoryAware {
    private static final Logger logger = LoggerFactory.getLogger(ShiroSessionDaoRedisAdapter.class);
    private static final String REDIS_SHIRO_SESSION = "shiro-session:";

    @Override
    public void saveSession(final Session session) {
        if (session == null || session.getId() == null) {
            return;
        }

        final byte[] key = SerializeUtil.serialize(getRedisSessionKey(session.getId()));
        final byte[] value = SerializeUtil.serialize(session);

        RedisUtil.post(new RedisUtil.JedisPostFunction<Long>() {
            @Override
            public Long post(ShardedJedis jedis) {
                Long timeOut = session.getTimeout() / 1000;
                jedis.set(key, value);
                return jedis.expire(key, Integer.parseInt(timeOut.toString()));
            }
        });
    }

    @Override
    public void deleteSession(final Serializable sessionId) {
        if (sessionId == null) {
            return;
        }
        RedisUtil.post(new RedisUtil.JedisPostFunction<Long>() {
            @Override
            public Long post(ShardedJedis jedis) {
                return jedis.del(SerializeUtil.serialize(getRedisSessionKey(sessionId)));
            }
        });

    }

    @Override
    public Session getSession(final Serializable sessionId) {
        if (sessionId == null) {
            return null;
        }
        Session session = RedisUtil.post(new RedisUtil.JedisPostFunction<Session>() {
            @Override
            public Session post(ShardedJedis jedis) {
                byte[] value = jedis.get(SerializeUtil
                        .serialize(getRedisSessionKey(sessionId)));
                return value == null ? null : (Session) SerializeUtil.unserialize(value);
            }
        });
        return session;
    }

    @Override
    public Collection<Session> getAllSessions() {

        return RedisUtil.post(new RedisUtil.JedisPostFunction<Set<Session>>() {
            @Override
            public Set<Session> post(ShardedJedis jedis) {
                Set<Session> sessions = new HashSet<>();

                Set<byte[]> byteKeys = jedis.hkeys(SerializeUtil
                        .serialize(ShiroSessionDaoRedisAdapter.REDIS_SHIRO_SESSION + "*"));
                if (byteKeys != null && byteKeys.size() > 0) {
                    for (byte[] bs : byteKeys) {
                        Session s = (Session) SerializeUtil.unserialize(jedis.get(bs));
                        sessions.add(s);
                    }
                }
                return sessions;
            }
        });
    }

    private String getRedisSessionKey(Serializable sessionId) {
        return this.REDIS_SHIRO_SESSION + sessionId;
    }

}
